#ifndef SPARCTRANSLATOR_H
#define SPARCTRANSLATOR_H

#include "crossbit/common.h"
#include "crossbit/VInst.h"
#include "crossbit/Translator.h"
#include "crossbit/RegAllocator.h"
#include "arch/ia32/IA32ProcessorState.h"

namespace crossbit {

    class TBlock;
    class VInst;

    class SPARCTranslator : public Translator {
        public:
            SPARCTranslator();
            SPARCTranslator(IA32ProcessorState * ps) : src_state(ps) , Translator(ps){
            }
            ~SPARCTranslator();
            void setBlockStub();
            XTRegNum SPARCRegAlloc(XTRegNum vreg);
            void initTranslation();
            void encode(VBlock *vb, TBlock *tb);

        private:    
	           IA32ProcessorState *src_state;
            VBlock *vblock;
            TBlock *tblock;
            // =========================================================
            //      Encoding Related
            XTMemAddr inst_buf; // instruction buffer
            XTMemAddr p_inst_buf;   // pointer to instruction buffer
            VInst *inst;    // current to-be-encoded virtual instruction
            // the loopAddr and labelAddr are used for Loop instruction
            XTMemAddr loopAddr[2];
            XTMemAddr labelAddr[2];
            // added on 2008-12-24
            // the temp instrcution is used to store the instruction of caluation indirect jump destionation 
            // in encodeBRANCH(), these instruction could be move into encodeExit() , so if the jump didn't happen
            // it will not calculate the destionation address any more. 
            XTUint32  temp_instruction_number;
            XTUint32  temp_instruction[16];
            void encodeBSR();
            void encodeBSF();
            void encodeLOOP();
            void encodeLOOPN();
            void encodeLABEL();
            void encodeGET();
            void encodePUT();
            void encodeLD();
            void encodeST();
            void encodeLI();
            void encodeMOV();
            void encodeSEXT();
            void encodeZEXT();
            void encodeADD();
            void encodeADDI();
            void encodeSUB();
            void encodeSUBI();
            void encodeAND();
            void encodeXOR();
            void encodeOR();
            void encodeNOT();
            void encodeMUL();
            void encodeMULU();
            void encodeDIV();
            void encodeDIVU();
            void encodeSLL();
            void encodeSLLV();
            void encodeSRL();
            void encodeSRLV();
            void encodeSRA();
            void encodeSRAV();
            void encodeCMP();
            void encodeJMP();
            void encodeBRANCH();
            void encodeSYSCALL();
            void encodeSBREAK();

            void encodeFPUTS();
            void encodeFGETS();
            void encodeFPUTD();
            void encodeFGETD();

            void encodeFLD();
            void encodeFST();
            void encodeFMOV();

            void encodeFADDS();
            void encodeFADDD();
            void encodeFSUBS();
            void encodeFSUBD();
            void encodeFMULS();
            void encodeFMULD();
            void encodeFDIVS();
            void encodeFDIVD();
            void encodeFNEGS();
            void encodeFNEGD();
            void encodeFABSS();
            void encodeFABSD();
            void encodeFSQRTS();
            void encodeFSQRTD();
            void encodeFCMPS();
            void encodeFCMPD();

            void encodeFCONV();
            void encodeFINCSTP();
            void encodeCALL();
            void encodeDIVU64();            
            void endOfBlock();
            void encodeExits();
            XTInt32 addTBlockExit(XTInt32 why, XTMemAddr next, XTInt32 exitOffset, VInst* v);
    };

}
#endif
